package com.example.aircraftwar.application.game;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Message;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;

import com.example.aircraftwar.R;
import com.example.aircraftwar.aircraft.*;
import com.example.aircraftwar.aircraftfactory.BossFactory;
import com.example.aircraftwar.aircraftfactory.EliteFactory;
import com.example.aircraftwar.aircraftfactory.MobFactory;
import com.example.aircraftwar.application.Explode;
import com.example.aircraftwar.application.HeroController;
import com.example.aircraftwar.application.ImageManager;
import com.example.aircraftwar.application.MainActivity;
import com.example.aircraftwar.application.loginorregister.LoginOrRegisterActivity;
import com.example.aircraftwar.application.network.NetConn;
import com.example.aircraftwar.bullet.AbstractBullet;
import com.example.aircraftwar.basic.AbstractFlyingObject;
import com.example.aircraftwar.prop.AbstractProp;
import com.example.aircraftwar.prop.BombProp;
import com.example.aircraftwar.startgame.StartGameActivity;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.List;

/**
 * 游戏主面板，游戏启动
 *
 * @author hitsz
 */
public abstract class Game extends SurfaceView implements SurfaceHolder.Callback,Runnable{

    private int backGroundTop = 0;

    /**
     * 时间间隔(ms)，控制刷新频率
     */
    private int timeInterval = 10;

    protected HeroAircraft heroAircraft;
    protected AbstractEnemy bossAircraft;
    protected final List<AbstractEnemy> enemyAircrafts;
    protected final List<AbstractBullet> heroBullets;
    protected final List<AbstractBullet> enemyBullets;
    protected final List<AbstractProp> props;
    protected final List<Explode> explodeObj;

    protected int enemyMaxNumber;

    /**
     * 道具掉落的概率
     */
    protected double probability;

    /**
     * 精英敌机产生的概率
     */
    protected double eliteProbability;

    public static int score = 0;
    public static int playscore = 0;
    protected int time = 0;
    /**
     * 周期（ms)
     * 指示敌机的产生频率
     */
    protected int enemyDuration;
    private int enemyCycleTime = 0;
    /**
     * 周期（ms)
     * 指示敌机子弹的发射频率
     */
    protected int enemyBulletDuration;
    private int enemyBulletCycleTime = 0;
    /**
     * 周期（ms)
     * 指示英雄机子弹的发射频率
     */
    protected int heroBulletDuration = 150;
    private int heroBulletCycleTime = 0;

    /**
     * Boss机产生的阈值
     */
    protected int bossScoreThreshold;

    /**
     * 是否产生Boss敌机
     */
    protected boolean createBoss;

    /**
     * 难度增加的间隔时间
     */
    protected int createdifficulty;

    /**
     * 敌机属性提升倍率
     */
    public static double magnification = 1;

    /**
     * 每次召唤Boss机的血量
     */
    public static int BossHp = 1000;

    private Context contextGame;

    /**
     * 控制绘画线程的标志位
     */
    public static boolean gameOverFlag;

    /**
     * 绘图的画布
     */
    private Canvas canvas;

    /**
     * 绘图的画笔
     */
    private Paint paint;
    private SurfaceHolder surfaceHolder;

    /**
     * 背景图片
     */
    protected Bitmap BACKGROUND_IMAGE;
    protected int bgHeight;

    /**
     * 背景图片速度
     */
    protected int bgSpeed;

    /**
     * 信息对象
     */
    private Message msg;

    public Game(Context contextGame) {
        super(contextGame);
        this.contextGame = contextGame;
        ImageManager.initImage(contextGame);
        paint = new Paint();  //设置画笔
        gameOverFlag = false;
        surfaceHolder = this.getHolder();
        surfaceHolder.addCallback(this);
        this.setFocusable(true);

        heroAircraft = HeroAircraft.creatHeroAircraft();
        bossAircraft = null;
        enemyAircrafts = new LinkedList<>();
        heroBullets = new LinkedList<>();
        enemyBullets = new LinkedList<>();
        props = new LinkedList<>();
        explodeObj = new LinkedList<>();

        //启动英雄机触摸监听
        new HeroController(this, heroAircraft);

        if (MainActivity.isonline) {
            //向服务器发送当前得分
            new Thread(() -> {
                while (true) {
                    try {
                        NetConn.writer.println(initJson().toString());
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        gameOverFlag = false;
        score = 0;
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
        gameOverFlag = true;
        heroAircraft = null;
        HeroAircraft.singleHero = null;
        playscore = score;
        StartGameActivity.myBinder.stopMusic();
    }

    @Override
    public void run() {
        if (StartGameActivity.isPlay) {
            StartGameActivity.myBinder.playBgm();
        }
        while (!gameOverFlag) {
            synchronized (surfaceHolder) {
                action();
            }
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 游戏启动入口，执行游戏逻辑
     */
    public void action() {

        time += timeInterval;

            // 周期性执行（控制频率）
        if (enemyTimeCountAndNewCycleJudge()) {
            System.out.println(time);
            // 新敌机产生
            if (enemyAircrafts.size() < enemyMaxNumber) {
                if(Math.random() <= eliteProbability){
                    enemyAircrafts.add(new EliteFactory().createAircraft());
                }
                else{
                    enemyAircrafts.add(new MobFactory().createAircraft());
                }
            }
        }

        //当得分每超过一次阈值bossScoreThreshold时，产生一次Boss机（同一时刻只有一架）
        if (bossAircraft == null && (score % bossScoreThreshold == 0) && (score != 0) && createBoss){
            createBoss();
        }

        if (enemyBulletDurationTimeCountAndNewCycleJudge()) {
            // 敌机射出子弹
            enemyShootAction();
        }
        if (heroBulletDurationTimeCountAndNewCycleJudge()) {
            // 英雄机射出子弹
            heroShootAction();
        }

        // 子弹移动
        bulletsMoveAction();

        // 飞机移动
        aircraftsMoveAction();

        //道具移动
        propsMoveAction();

        // 撞击检测
        try {
            crashCheckAction();
        } catch (InterruptedException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
            e.printStackTrace();
        }

        // 后处理
        postProcessAction();

        //每个时刻重绘界面
        draw();

        //提高难度
        increaseddifficulty();

        // 游戏结束检查
        if (heroAircraft.getHp() <= 0) {
//                //添加英雄机爆炸效果
//                explodeObj.add(new Explode(heroAircraft.getLocationX(),heroAircraft.getLocationY()));
//                explodeObj.get(explodeObj.size() - 1).paint(g);
            // 游戏结束
//                executorService.shutdown();
            gameOverFlag = true;
            if (StartGameActivity.isPlay) {
                StartGameActivity.myBinder.stopMusic();
                StartGameActivity.myBinder.playGameOver();
            }
            System.out.println("Game Over!");
            if (!MainActivity.isonline) {
                msg = Message.obtain();
                msg.what = 2;
                MainActivity.mhandler.sendMessage(msg);
            }
        }

    }

    //***********************
    //      Action 各部分
    //***********************

    private JSONObject initJson() throws JSONException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username", LoginOrRegisterActivity.userName);
//        if (gameOverFlag) {
//            jsonObject.put("score", playscore);
//        } else {
            jsonObject.put("score", score);
//        }
        System.out.println(LoginOrRegisterActivity.userName);
        System.out.println("当前得分" + score);
        jsonObject.put("gameoverflag", gameOverFlag);
        return jsonObject;
    }

    public void createBoss() {
        if (StartGameActivity.isPlay) {
            StartGameActivity.myBinder.playBgmBoss();
        }
        bossAircraft = new BossFactory().createAircraft();
    }

    private boolean enemyTimeCountAndNewCycleJudge() {
        enemyCycleTime += timeInterval;
        if (enemyCycleTime >= enemyDuration && enemyCycleTime - timeInterval < enemyCycleTime) {
            // 跨越到新的周期
            enemyCycleTime %= enemyDuration;
            return true;
        } else {
            return false;
        }
    }

    private boolean enemyBulletDurationTimeCountAndNewCycleJudge() {
        enemyBulletCycleTime += timeInterval;
        if (enemyBulletCycleTime >= enemyBulletDuration && enemyBulletCycleTime - timeInterval < enemyBulletCycleTime) {
            // 跨越到新的周期
            enemyBulletCycleTime %= enemyBulletDuration;
            return true;
        } else {
            return false;
        }
    }

    private boolean heroBulletDurationTimeCountAndNewCycleJudge() {
        heroBulletCycleTime += timeInterval;
        if (heroBulletCycleTime >= heroBulletDuration && heroBulletCycleTime - timeInterval < heroBulletCycleTime) {
            // 跨越到新的周期
            heroBulletCycleTime %= heroBulletDuration;
            return true;
        } else {
            return false;
        }
    }

    private void enemyShootAction() {
        // TODO 敌机射击
        for(AbstractEnemy enemyaircraft : enemyAircrafts){
            enemyBullets.addAll(enemyaircraft.shoot());
        }
        if (bossAircraft != null) {
            enemyBullets.addAll(bossAircraft.shoot());
        }
    }

    private void heroShootAction() {
        // 英雄机射击
        heroBullets.addAll(heroAircraft.shoot());
    }

    private void bulletsMoveAction() {
        for (AbstractBullet bullet : heroBullets) {
            bullet.forward();
        }
        for (AbstractBullet bullet : enemyBullets) {
            bullet.forward();
        }
    }

    private void propsMoveAction() {
        for (AbstractProp prop : props) {
            prop.forward();
        }
    }

    private void aircraftsMoveAction() {
        for (AbstractEnemy enemyAircraft : enemyAircrafts) {
            enemyAircraft.forward();
        }
        if (bossAircraft != null) {
            bossAircraft.forward();
        }
    }


    /**
     * 碰撞检测：
     * 1. 敌机攻击英雄
     * 2. 英雄攻击/撞击敌机
     * 3. 英雄获得补给
     */
    private void crashCheckAction() throws InterruptedException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // TODO 敌机子弹攻击英雄
        for(AbstractBullet bullet : enemyBullets){
            if (bullet.notValid()) {
                continue;
            }
            if (heroAircraft.crash(bullet)) {
                // 英雄机撞击到敌机子弹
                // 英雄机损失一定生命值
                heroAircraft.decreaseHp(bullet.getPower());
                if(StartGameActivity.isPlay) {
                    StartGameActivity.myBinder.playBulletHit();
                }
                bullet.vanish();
            }
        }
        // 英雄子弹攻击敌机
        for (AbstractBullet bullet : heroBullets) {
            if (bullet.notValid()) {
                continue;
            }
            if (bossAircraft != null && !bossAircraft.notValid() && bossAircraft.crash(bullet) && createBoss) {
                if(StartGameActivity.isPlay) {
                    StartGameActivity.myBinder.playBulletHit();
                }
                bossAircraft.decreaseHp(bullet.getPower());
                bullet.vanish();
                if (bossAircraft.notValid()) {
                    score += 20;
                    if(StartGameActivity.isPlay) {
                        StartGameActivity.myBinder.playBombExplosion();
                        StartGameActivity.myBinder.playBgm();
                    }
                    explodeObj.add(new Explode(bossAircraft.getLocationX()-50,bossAircraft.getLocationY()-50));
                    if(Math.random() <= probability) {
                        props.add(bossAircraft.drop());
                    }
                }
                continue;
            }
            for (AbstractEnemy enemyAircraft : enemyAircrafts) {
                if (enemyAircraft.notValid()) {
                    // 已被其他子弹击毁的敌机，不再检测
                    // 避免多个子弹重复击毁同一敌机的判定
                    continue;
                }
                if (enemyAircraft.crash(bullet)) {
                    // 敌机撞击到英雄机子弹
                    // 敌机损失一定生命值
                    enemyAircraft.decreaseHp(bullet.getPower());
                    if(StartGameActivity.isPlay) {
                        StartGameActivity.myBinder.playBulletHit();
                    }
                    bullet.vanish();
                    if (enemyAircraft.notValid()) {
                        // TODO 获得分数，产生道具补给
                        score += 10;
                        if(StartGameActivity.isPlay) {
                            StartGameActivity.myBinder.playBombExplosion();
                        }
                        explodeObj.add(new Explode(enemyAircraft.getLocationX()-70,enemyAircraft.getLocationY()-50));
                        if(enemyAircraft.getClass().getName().equals("com.example.aircraftwar.aircraft.EliteEnemy") && Math.random() <= probability){
                            props.add(enemyAircraft.drop());
                        }
                    }
                }
                // 英雄机 与 敌机 相撞，均损毁
                if (enemyAircraft.crash(heroAircraft) || heroAircraft.crash(enemyAircraft)) {
                    enemyAircraft.vanish();
                    heroAircraft.decreaseHp(Integer.MAX_VALUE);
                    if(StartGameActivity.isPlay) {
                        StartGameActivity.myBinder.playBombExplosion();
                    }
                }
                // 英雄机 与 boss机 相撞，均损毁
                if (bossAircraft != null && (bossAircraft.crash(heroAircraft) || heroAircraft.crash(bossAircraft))) {
                    enemyAircraft.vanish();
                    heroAircraft.decreaseHp(Integer.MAX_VALUE);
                    if(StartGameActivity.isPlay) {
                        StartGameActivity.myBinder.playBombExplosion();
                    }
                }
            }
        }

        // Todo: 我方获得道具，道具生效
        for(AbstractProp prop : props){
            if (heroAircraft.crash(prop)){
                prop.vanish();
                if(StartGameActivity.isPlay) {
                    StartGameActivity.myBinder.playGetSupply();
                }
                if ("com.example.aircraftwar.prop.BombProp".equals(prop.getClass().getName())) {
                    BombProp.class.getMethod("addSubscriber",List.class,List.class).invoke(prop,enemyAircrafts,enemyBullets);
                    prop.effect(heroAircraft,explodeObj);
                    if(StartGameActivity.isPlay) {
                        StartGameActivity.myBinder.playBombExplosion();
                    }
                } else {
                    prop.effect(heroAircraft,explodeObj);
                }
            }
        }
    }

    /**
     * 后处理：
     * 1. 删除无效的子弹
     * 2. 删除无效的敌机
     * 3. 检查英雄机生存
     * <p>
     * 无效的原因可能是撞击或者飞出边界
     */
    private void postProcessAction() {
        enemyBullets.removeIf(AbstractFlyingObject::notValid);
        heroBullets.removeIf(AbstractFlyingObject::notValid);
        enemyAircrafts.removeIf(AbstractFlyingObject::notValid);
        props.removeIf(AbstractFlyingObject::notValid);
        explodeObj.removeIf(AbstractFlyingObject::notValid);
        if (bossAircraft != null && bossAircraft.notValid()) {
            bossAircraft = null;
        }
    }

    /**
     * 提高难度
     */
    public abstract void increaseddifficulty();


    //***********************
    //      Paint 各部分
    //***********************

    public void draw() {
        canvas = surfaceHolder.lockCanvas();

        if(surfaceHolder == null || canvas == null){
            return;
        }
        // 绘制背景,图片滚动
        bgHeight = BACKGROUND_IMAGE.getHeight();
        canvas.drawBitmap(BACKGROUND_IMAGE,(float) 0,(float) (this.backGroundTop - bgHeight),paint);
        canvas.drawBitmap(BACKGROUND_IMAGE, 0, this.backGroundTop, null);
        this.backGroundTop += bgSpeed;
        if (this.backGroundTop >= bgHeight) {
            this.backGroundTop = 0;
        }

        // 先绘制子弹，后绘制飞机
        // 这样子弹显示在飞机的下层
        paintImageWithPositionRevised(canvas, enemyBullets);
        paintImageWithPositionRevised(canvas, heroBullets);

        paintImageWithPositionRevised(canvas, enemyAircrafts);

        canvas.drawBitmap(ImageManager.HERO_IMAGE, heroAircraft.getLocationX() - ImageManager.HERO_IMAGE.getWidth() / 2,
                heroAircraft.getLocationY() - ImageManager.HERO_IMAGE.getHeight() / 2, null);

        if (bossAircraft != null) {
            canvas.drawBitmap(ImageManager.BOSS_ENEMY_IMAGE, bossAircraft.getLocationX() - ImageManager.BOSS_ENEMY_IMAGE.getWidth() / 2,
                    bossAircraft.getLocationY() - ImageManager.BOSS_ENEMY_IMAGE.getHeight() / 2, null);
        }

        //绘制爆炸效果
        for(Explode explodeobj : explodeObj) {
            for (int i = 0;i < 16;i++){
                canvas.drawBitmap(ImageManager.EXPLODE_IMAGE[i],-1000,-1000,null);
            }
            if(explodeobj.getExplodeCount() < 16){
                canvas.drawBitmap(ImageManager.EXPLODE_IMAGE[explodeobj.getExplodeCount()],explodeobj.getLocationX(),explodeobj.getLocationY(),null);
                explodeobj.setExplodeCount(explodeobj.getExplodeCount() + 1);
            }
            if (explodeobj.getExplodeCount() == 15){
                explodeobj.vanish();
            }
        }
        //绘制道具
        paintImageWithPositionRevised(canvas,props);
        //绘制得分和生命值
        paintScoreAndLife(canvas);
        surfaceHolder.unlockCanvasAndPost(canvas);
    }

    private void paintImageWithPositionRevised(Canvas canvas, List<? extends AbstractFlyingObject> objects) {
        if (objects.size() == 0) {
            return;
        }

        for (AbstractFlyingObject object : objects) {
            Bitmap image = object.getImage();
            assert image != null : objects.getClass().getName() + " has no image! ";
            canvas.drawBitmap(image, object.getLocationX() - image.getWidth() / 2,
                    object.getLocationY() - image.getHeight() / 2, paint);
        }
    }

    private void paintScoreAndLife(Canvas canvas) {
        int x = 20;
        int y = 100;
        paint.setColor(this.getResources().getColor(R.color.red));
        paint.setTextSize(80f);
        canvas.drawText("您的得分:" + this.score, x, y,paint);
        y = y + 80;
        canvas.drawText("剩余血量:" + this.heroAircraft.getHp(), x, y,paint);
        if (MainActivity.isonline) {
            y = y + 80;
            canvas.drawText("对方得分:" + GameActivity.enemyScore, x, y,paint);
        }
//        paint.setFont(new Font("SansSerif", Font.BOLD, 22));
    }

}
